package com.temi.demo.net;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.pubnub.api.PNConfiguration;
import com.pubnub.api.PubNub;
import com.pubnub.api.callbacks.PNCallback;
import com.pubnub.api.callbacks.SubscribeCallback;
import com.pubnub.api.models.consumer.PNPublishResult;
import com.pubnub.api.models.consumer.PNStatus;
import com.pubnub.api.models.consumer.pubsub.PNMessageResult;
import com.pubnub.api.models.consumer.pubsub.PNPresenceEventResult;
import com.temi.demo.MainActivity;
import com.temi.demo.MyApplication;
import com.temi.demo.R;
import com.temi.demo.bean.ContactsListResult;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;

/**
 * Created by coco on 2018/6/27.
 */

public class PubNubManager {

    private PubNub pubnub;
    public static PubNubManager pubNubManager;

    private PubNubManager() {
    }

    public static PubNubManager getInstance() {
        if (pubNubManager == null) {
            synchronized (PubNubManager.class) {
                if (pubNubManager == null) {
                    pubNubManager = new PubNubManager();
                }
            }
        }

        return pubNubManager;
    }

    public PubNubManager initPubNub() {
        if (pubnub == null) {
            PNConfiguration pnConfiguration = new PNConfiguration();
            pnConfiguration.setSubscribeKey(MyApplication.mContext.getResources().getString(R.string.subscribe_key));
            pnConfiguration.setPublishKey(MyApplication.mContext.getResources().getString(R.string.publish_key));
            pnConfiguration.setSecure(false);

            pubnub = new PubNub(pnConfiguration);
        }

        return pubNubManager;
    }

    public PubNubManager addSubscribeListener() {
        pubnub.addListener(new SubscribeCallback() {
            @Override
            public void status(PubNub pubnub, PNStatus status) {
                switch (status.getOperation()) {
                    case PNSubscribeOperation:
                    case PNUnsubscribeOperation:
                        switch (status.getCategory()) {
                            case PNConnectedCategory:
                                // this is expected for a subscribe, this means there is no error or issue whatsoever
                                Log.i("COCO", "connection");
                            case PNReconnectedCategory:
                            case PNDisconnectedCategory:
                            case PNUnexpectedDisconnectCategory:
                            case PNTimeoutCategory:
                                pubnub.reconnect();
                                break;
                            case PNAccessDeniedCategory:
                                // this means that PAM does allow this client to subscribe to this
                                // channel and channel group configuration. This is another explicit error
                            default:
                                // More errors can be directly specified by creating explicit cases for other
                                // error categories of `PNStatusCategory` such as `PNTimeoutCategory` or `PNMalformedFilterExpressionCategory` or `PNDecryptionErrorCategory`
                        }

                    case PNHeartbeatOperation:
                        // heartbeat operations can in fact have errors, so it is important to check first for an error.
                        // For more information on how to configure heartbeat notifications through the status
                        // PNObjectEventListener callback, consult <link to the PNCONFIGURATION heartbeart config>
                        if (status.isError()) {
                            // There was an error with the heartbeat operation, handle here
                        } else {
                            // heartbeat operation was successful
                        }
                    default: {
                        // Encountered unknown status type
                    }
                }
            }

            @Override
            public void message(PubNub pubnub, PNMessageResult message) {
                String messagePublisher = message.getPublisher();
                Log.i("COCO", "Message publisher: " + messagePublisher);
                Log.i("COCO", "Message Payload: " + message.getMessage());
                Log.i("COCO", "Message Subscription: " + message.getSubscription());
                Log.i("COCO", "Message Channel: " + message.getChannel());
                Log.i("COCO", "Message timeToken: " + message.getTimetoken());

                ArrayList<String> list = new Gson().fromJson(message.getMessage(),
                        new TypeToken<ArrayList<String>>() {
                        }.getType());
                notification("title", list.get(0));
            }

            @Override
            public void presence(PubNub pubnub, PNPresenceEventResult presence) {

            }
        });

        return pubNubManager;
    }

    public PubNubManager subscribeMessage(String... channel) {
        pubnub.subscribe()
                .channels(Arrays.asList(channel)) // subscribe to channels
                .execute();

        return pubNubManager;
    }

    public PubNubManager publishMessage(String... Msg) {
        pubnub.publish()
                .message(Arrays.asList(Msg))
                .channel("test")
                .async(new PNCallback<PNPublishResult>() {
                    @Override
                    public void onResponse(PNPublishResult result, PNStatus status) {
                        // handle publish result, status always present, result if successful
                        // status.isError to see if error happened

                        //temporary
                        unSubscribe("test");
                    }
                });

        return pubNubManager;
    }

    public PubNubManager unSubscribe(String... channel) {
        pubnub.unsubscribe()
                .channels(Arrays.asList(channel))
                .execute();

        return pubNubManager;
    }


    public PubNubManager destroyPubub() {
        pubnub.destroy();
        return pubNubManager;
    }

    protected void notification(String iTitle, String iMessage) {
        NotificationManager notificationManager = (NotificationManager) MyApplication.mContext.getSystemService(Context.NOTIFICATION_SERVICE);
        Notification.Builder builder = new Notification.Builder(MyApplication.mContext);

        int notificationIcon = R.mipmap.ic_launcher_round;
        long when = System.currentTimeMillis();

        Intent intent = new Intent(MyApplication.mContext, MainActivity.class);
        intent.setAction(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);

        int requestCode, notificationId;

        final Random random = new Random(System.currentTimeMillis());
        requestCode = random.nextInt();
        notificationId = random.nextInt();

        PendingIntent contentIntent = PendingIntent.getActivity(MyApplication.mContext, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        builder.setContentIntent(contentIntent)
                .setSmallIcon(notificationIcon).setTicker(iTitle)
                .setContentTitle(iTitle)
                .setContentText(iMessage)
                .setWhen(when).setAutoCancel(true);
        Notification notification = builder.getNotification();
        notification.defaults = Notification.DEFAULT_ALL;
        assert notificationManager != null;
        notificationManager.notify(notificationId, notification);
    }

}
